/*
装饰器：装饰器是一种特殊类型的声明，它能够被附加到类声明，方法，属性或参数上，可以修改类的行为。
通俗的讲 装饰器就是一个方法，可以注入到类，方法，属性参数上来扩展类、属性、方法、参数的功能。
常见的装饰器有：类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法：普通装饰器（无法传参）、装饰器工厂（可传参）
装饰器是过去几年中 js最大的成就之一 已是es7的标准特性之一
*/
// 类装饰器
// 类装饰器在类声明之前被声明（紧靠着类声明）。
//类装饰器应用于类构造函数，可以用来监视、修改或替换类定义。

// 普通装饰器  无传参
// function logClass(params:any){
//   console.log(params);
//   // params 当前类
//   // 可扩展 属性 方法
//   params.prototype.apiUrl='www.baidu.com'
//   params.prototype.run =function(){
//     console.log('我是run方法');
//   }
// }
// // 调用（无传参）
// @logClass
// class HttpClient{
//   constructor(){

//   }
//   getData(){

//   }
// }

// let hh:any = new HttpClient()

// console.log(hh.apiUrl); //www.baidu.com

// 装饰器工厂 （可传参）常用

// function logClass(params:string){
//   return function(target:any){
//    console.log(target,'target');
//    console.log(params,'params');
//   //  扩展 属性 方法
//   target.prototype.apiUrl="www.baidu.com"
//   target.prototype.run =function(){
//     console.log('我是run方法');
//   }
//   }
// }
// @logClass('hello')

// class HttpClient{
//   constructor(){

//   }
//   getData(){

//   }
// }

// let hh2:any = new HttpClient()
// console.log(hh2.apiUrl);
// console.log(hh2.run);

// 属性装饰器
// 属性装饰器表达式会在运行时当作函数被调用
// 传入下列2个参数
// 1.对于静态成员来说是构造函数，对于实例成员来说是类的原型对象
// 2.成员的名字

// function logPrototype(params: any) {
//   console.log(params, 'params')
//   return function (target: any, attr: any) {
//     console.log(target, 'target')
//     console.log(attr, 'attr')
//     target[attr] = params
//   }
// }

// class HttpClient {
//   @logPrototype('www.baidu.com')
//   public url: string | undefined
//   constructor() {}
//   getData() {
//     console.log(this.url)
//   }
// }

// let hh3 = new HttpClient()
// console.log(hh3.getData())

// 方法装饰器
// 它会被应用到方法的属性描述符上，可以用来监视、修改或者替换方法定义。
// 方法装饰器会在运行时传入下列3个参数
// 1.对于静态成员来说是类的构造函数，对于实例成员是类的原型对象
// 2.成员的名字
// 3.成员的属性描述符

// function logMethod(params: any) {
//   return function (target: any, methodsName: any, desc: any) {
//     console.log(target, 'target')
//     console.log(methodsName, 'methodsName') //getData
//     console.log(desc, 'desc')
//     target.url = 'xxx'
//     target.run = function () {
//       console.log('run方法')
//     }
//   }
// }

// class HttpClient {
//   public url: string | undefined
//   constructor() {}
//   @logMethod('www.baidu.com')
//   getData() {
//     console.log(this.url)
//   }
// }

// let hh4: any = new HttpClient()
// console.log(hh4.url)
// console.log(hh4.run())

// 修改当前方法
// function logMethod(params: any) {
//   return function (target: any, methodsName: any, desc: any) {
//     console.log(target, 'target')
//     console.log(methodsName, 'methodsName') //getData
//     console.log(desc.value, 'desc')
//     //  修改装饰器的方法 把装饰器方法里面传入的所有参数改为string类型
//     desc.value = function (...args: any[]) {
//       args = args.map((value) => {
//         return String(value)
//       })
//     }
//   }
// }

// class HttpClient {
//   public url: string | undefined
//   constructor() {}
//   @logMethod('www.baidu.com')
//   getData() {
//     console.log(this.url)
//   }
// }

// let hh4: any = new HttpClient()

// 方法参数装饰器
// 参数装饰器表达式会在运行时当作函数被调用，可以使用参数装饰器为类的原型增加一些元素数据
// 传入以下3个参数
// 1.对于静态成员来说是类的构造函数，对于实例成员是类的原型对象
// 2.参数的名字
// 3.参数在函数参数列表中的索引

function logParams(params: any) {
  return function (target: any, paramsName: any, paramsIndex: any) {
    console.log(target, 'target')
    console.log(paramsName, 'paramsName')
    console.log(paramsIndex, 'paramsIndex')
  }
}

class HttpClient {
  constructor() {}
  getData(@logParams('uuid') uuid: any) {
    console.log(uuid) //123456
  }
}

let hh4: any = new HttpClient()
console.log(hh4.getData(123456))
